# -*- coding: utf-8 -*-

from odoo import models, fields, api
from odoo.exceptions import UserError
from odoo.tools import float_is_zero, float_compare


class ApproveRecords(models.Model):
    _name = "approval.records"

    """
    按照部門架構簽核的簽核記錄表
    """
    _order = 'id desc'

    res_id = fields.Integer(string=u"關聯model數據庫ID")

    res_model = fields.Char(string=u"關聯model名")

    user_id = fields.Many2one('res.users', string=u"签核人")

    status = fields.Selection([
        ('0', '通过'),
        ('1', '拒绝'),
        ('2', '提交'),
        ('3', '撤回'),
        ('4', '會簽')
    ], string=u"签核状态")

    remark = fields.Char(string=u"备注")


class BaseApprove(models.AbstractModel):
    _name = "base.approve"

    state = fields.Selection([
        ('draft', u'草稿'),
        ('cancel', u'取消'),
        ('to approve', u'待审核'),
        ('rejected', u'拒绝'),
        ('done', u'完成'),
    ], string=u"状态", default='draft', track_visibility='onchange')
    # 記錄目前審核階段
    stage_sequence = fields.Integer(copy=False)
    to_approve_user_id = fields.Many2one('res.users')

    user_can_approve = fields.Boolean(compute='compute_user_can_approve')
    user_can_submit = fields.Boolean(compute='compute_user_can_submit')
    user_can_retract = fields.Boolean(compute="_compute_user_can_retract")
    approve_id = fields.Many2one('res.users', string=u'簽核人',copy=False)
    approval_record_ids = fields.One2many('approval.records', 'res_id',domain=lambda self: [('res_model', '=', self._name)])
    approve_flow_ids = fields.One2many('approve.flow', 'res_id',domain=lambda self: [('res_model', '=', self._name)])
    remark = fields.Char(string=u'备注')

    #
    # @api.multi
    # def _message_auto_subscribe_notify(self, partner_ids, template):
    #     """ Notify new followers, using a template to render the content of the
    #     notification message. Notifications pushed are done using the standard
    #     notification mechanism in mail.thread. It is either inbox either email
    #     depending on the partner state: no user (email, customer), share user
    #     (email, customer) or classic user (notification_type)
    #
    #     :param partner_ids: IDs of partner to notify;
    #     :param template: XML ID of template used for the notification;
    #
    #
    #     """
    #     print('111111111111111111111')
    #     return

    def get_total_amount(self):
        if hasattr(self, 'total_amount'):

            return self.total_amount
        else:
            return self.amount_total

    def get_sheet_employee_id(self):
        if hasattr(self, 'employee_id'):

            return self.employee_id
        else:
            return self.user_id.employee_ids[0]

    def _set_approve_user_id(self, user_id):
        if not user_id:
            #self.button_approve()
            return
            # raise UserError(u'找不到審核人')
        if not user_id.partner_id:
            raise UserError(u'找不到簽核人對應聯絡人')
        self.to_approve_user_id = user_id.id
        self.send_to_approve_email(user_id)

    def send_to_approve_email(self, user_id):
        pass
    def get_sheet_level(self):
        return self.type_id.level

    def create_approve_flow(self):
        Flow = self.env['approve.flow']
        custom_flow_ids = self.env['base.approve.flow'].search([('res_model', '=', self._name),('department_id','=',self.department_id.id)])
        if not custom_flow_ids:
            custom_flow_ids = self.env['base.approve.flow'].search(
                [('res_model', '=', self._name)])
        if custom_flow_ids:
            line_ids = custom_flow_ids[0].line_ids
            if not line_ids:
                raise UserError('没找到相关审核流程')
            amount = self.get_total_amount()
            seq = 10
            for line in line_ids:
                Flow.create({
                    'sequence': seq,
                    'res_id': self.id,
                    'res_model': self._name,
                    'approve_type': 'normal',
                    'user_id': line.user_id.id,
                    'remark': u'主管签核',
                    'amount': line.amount

                })
                seq = seq + 10
                if amount > line.amount:
                    continue
                else:
                    break
        elif hasattr(self, '_approve_by_level') and self._approve_by_level:
            Flow = self.env['approve.flow']
            department_id = self.department_id
            sheet_level = self.get_sheet_level()
            level = 1
            auth_department_ids = department_id.get_parent_departments(parents=[department_id])
            if auth_department_ids:

                seq = 10
                for d in auth_department_ids:
                    if level <= sheet_level:
                        user_id = d.manager_id.user_id.id
                        if not user_id:
                            continue
                            # raise UserError('找不到部门负责人或者相关用户')
                        Flow.create({
                            'sequence': seq,
                            'res_id': self.id,
                            'res_model': self._name,
                            'approve_type': 'normal',
                            'user_id': user_id,
                            'remark': u'主管签核',
                        })
                        seq = seq + 10
                        level += 1
        else:
            employee_id = self.get_sheet_employee_id()
            if hasattr(self, 'department_id') and self.department_id:
                department_id = self.department_id
            else:
                department_id = employee_id.department_id
            if department_id.manager_id.user_id == employee_id.user_id and self.create_uid == employee_id.user_id:
                department_id = department_id.parent_id
            # 如果沒有上級部門,本部門籤核一下
            if not department_id:
                department_id = employee_id.department_id
            auth_department_ids = self.get_approve_departments(department_id, self.get_total_amount(), parents=[])
            if auth_department_ids:
                seq = 10
                for d in auth_department_ids:
                    user_ids = []
                    if not d.manager_id:
                        continue
                    user_id = d.manager_id.user_id.id
                    if user_id in user_ids:
                        pass
                    approve_line = d.auth_id.approve_line_ids.filtered(lambda x: x.model == self._name)

                    if not approve_line:
                        continue
                        # raise UserError('未找到%s對應%s的簽核權限' % (department_id.name, self._description))
                    Flow.create({
                        'sequence': seq,
                        'res_id': self.id,
                        'res_model': self._name,
                        'approve_type': 'normal',
                        'user_id': user_id,
                        'remark': u'主管签核',
                        'amount': approve_line.amount

                    })
                    seq = seq + 10

    def get_approve_departments(self, department, amount, parents=[]):
        approve_line = department.auth_id.approve_line_ids.filtered(lambda x: x.model == self._name)

        if not approve_line:
            raise UserError('未找到%s對應%s的簽核權限' % (department.name, self._description))
        auth_amount = approve_line.amount

        if department.parent_id and auth_amount < amount:
            if department.parent_id.manager_id != department.manager_id:
                parents.append(department)
            return self.get_approve_departments(department.parent_id, amount, parents)
        else:
            parents.append(department)
            return parents

    @api.model
    def search_read(self, domain=None, fields=None, offset=0, limit=None, order=None):
        args = domain or []
        if self._context.get('approve_type') == 'submitted' and self.env.user.employee_ids:
            approvals = self.env['approval.records'].search([
                ('res_model', '=', self._name),
                ('status', '=', '2'),
                ('user_id', '=', self.env.user.employee_ids[0].id)
            ])
            res_ids = approvals.mapped('res_id')
            domain = [('id', 'in', res_ids), ('state', 'not in', ('draft', 'rejected'))]
            args = domain + args
        elif self._context.get('approve_type') == 'approved' and self.env.user.employee_ids:

            approvals = self.env['approval.records'].search([
                ('res_model', '=', self._name),
                ('status', 'in', ['0', '1']),
                ('user_id', '=', self.env.user.employee_ids[0].id)
            ])
            res_ids = approvals.mapped('res_id')
            domain = [('id', 'in', res_ids)]
            args = domain + args
        return super(BaseApprove, self).search_read(domain=args, fields=fields, offset=offset, limit=limit,
                                                    order=order)

    def create_approve_record(self, remark='', status=False):
        self.env['approval.records'].create({
            'res_id': self.id,
            'res_model': self._name,
            'remark': remark,
            'user_id': self.env.user.id,
            'status': status
        })

    @api.model
    def _needaction_domain_get(self):
        """ Returns the domain to filter records that require an action
            :return: domain or False is no action
        """

        if self._context.get('approve_type') == 'to_submit':
            return [('state', 'in', ('draft', 'rejected')), ('create_uid', '=', self.env.user.id)]
        if self._context.get('approve_type') == 'to_approve':
            return [('to_approval_employee_id.user_id', '=', self.env.user.id)]

    has_approve_flow_ids = fields.Boolean(compute="compute_has_approve_flow_ids")

    def compute_has_approve_flow_ids(self):
        for r in self:
            if r.approve_flow_ids:
                r.has_approve_flow_ids = True
            else:
                r.has_approve_flow_ids = False

    def compute_user_can_submit(self):
        for r in self:
            if r.create_uid == self.env.user:
                r.user_can_submit = True
            else:
                r.user_can_submit = False

    def _compute_user_can_retract(self):
        for record in self:

            if record.user_id.id == self.env.uid:
                record.user_can_retract = True
            else:
                record.user_can_retract = False

            if self.env.user.has_group('base.group_erp_manager') and record.state == 'to approve':
                record.user_can_retract = True

    def compute_user_can_approve(self):
        for r in self:
            if not self.env.user.employee_ids:
                r.user_can_approve = False
            if r.to_approve_user_id and r.to_approve_user_id.id == self.env.user.id:
                r.user_can_approve = True
            else:
                r.user_can_approve = False

    def get_approve_department_id(self):
        return self.department_id

    def action_comment(self):
        """
        审核动作
        :return:
        """
        return {
            'type': 'ir.actions.act_window',
            'name': u'簽核意見',
            'res_model': 'to.approval.action.wizard',
            'view_mode': 'form',
            'context': {'default_res_id': self.id, 'default_res_model': self._name},
            'view_id': self.env.ref('base_apporval.approval_comment_wizard_form').id,
            'target': 'new'
        }

    def action_account_reject(self):
        """
        审核动作
        :return:
        """
        return {
            'type': 'ir.actions.act_window',
            'name': u'签核意见',
            'res_model': 'to.approval.action.wizard',
            'view_mode': 'form',
            'context': {'default_res_id': self.id, 'default_res_model': self._name},
            'view_id': self.env.ref('base_apporval.approval_account_reject_wizard_form').id,
            'target': 'new'
        }

    def action_retract(self):
        """
        撤回的动作
        :return:
        """
        return {
            'type': 'ir.actions.act_window',
            'name': u'撤回',
            'res_model': 'to.approval.action.wizard',
            'view_mode': 'form',
            'context': {'default_res_id': self.id, 'default_res_model': self._name},
            'view_id': self.env.ref('base_apporval.approval_retract_wizard_form').id,
            'target': 'new'
        }

    def check_values(self):
        if not self.approve_flow_ids:
            self.create_approve_flow()
            if not self.approve_flow_ids:
                raise UserError('请检查部门权限设置，没有找到相关签核流')

            # raise UserError('請先產生簽核流程')
        """
        用于检查是否可以提交
        有一比费用要通知你

        指挥你
        :return:
        """

    def set_to_to_approve(self):
        self.state = 'to approve'

    def get_to_approve_from_approve_flow(self):
        """
        找下一个 审核人
        """
        if not self.stage_sequence:
            approve_lines = self.approve_flow_ids
            approve_line = approve_lines[0]
            to_approve_id = approve_line.user_id
            stage_sequence = approve_line.sequence

        else:
            next_approve_lines = self.approve_flow_ids.filtered(
                lambda x: x.sequence > self.stage_sequence)
            if next_approve_lines:
                to_approve_id = next_approve_lines[0].user_id
                stage_sequence = next_approve_lines[0].sequence
            else:
                to_approve_id = False
                stage_sequence = False
        return to_approve_id, stage_sequence

    # 提交审核
    def action_submit(self, need_notification=False):
        # 提交人即为该单据负责人，退回的时候可以退给他
        # 创建审核记录
        self.check_values()
        self.create_approve_record(status='2')
        self.set_to_to_approve()
        to_approve_id, sequence = self.get_to_approve_from_approve_flow()
        self.stage_sequence = sequence
        self.with_context(tracking_disable=True)._set_approve_user_id(to_approve_id)

    def action_cancel(self):
        if self.state == 'draft':
            self.state = 'cancel'

    def action_set_to_draft(self):
        if self.state == 'cancel':
            self.state = 'draft'

    def action_reject(self, remark='', need_notification=False):
        if remark:
            reject_str = u"拒絕原因：" + remark
            self.message_post(body=reject_str)
        self.remark = remark if remark else ''

        self.create_approve_record(status='1', remark=remark)
        self.set_to_reject()
        self.to_approve_user_id = False
        self.stage_sequence = 0

    def action_approve(self, remark=''):
        for record in self:

            # 檢查使用者就是待簽核人及狀態
            if not record.state == 'to approve':
                raise UserError('单据不是待审核')

            if not record.to_approve_user_id == record.env.user:
                raise UserError('单据审核人不是您，请重新确认')
            record.create_approve_record(status='0', remark=remark)
            reject_str = "审核通过：" + remark
            record.message_post(body=reject_str)
            current_approve_id = record.approve_flow_ids.filtered(lambda x: x.sequence == record.stage_sequence).user_id
            if current_approve_id != self.env.user:
                raise UserError(u'您已經签核通过,请不要重复签核')

            to_approve_user_id, stage_sequence = record.get_to_approve_from_approve_flow()
            if to_approve_user_id:
                record.stage_sequence = stage_sequence
                if len(self) > 1:
                    need_email = False
                else:
                    need_email = True

                record._set_approve_user_id(to_approve_user_id)
            else:
                record.action_approve_done()

    # 撤回
    def action_cancel_approval(self, remark=False):
        if remark:
            reject_str = u"撤回原因：" + remark
            self.message_post(body=reject_str)
        self.create_approve_record(status='3', remark=remark)
        self.state = "draft"
        self.to_approve_user_id = False
        self.stage_sequence = 0
        self.approve_flow_ids.unlink()

    def set_to_reject(self):
        self.state = 'rejected'
        self.approve_flow_ids.unlink()

    def set_to_done(self):
        self.state = 'done'

    def action_approve_done(self, need_notification=False):

        self.approve_id = self.env.user.id
        self.to_approve_user_id = False
        self.set_to_done()

    def unlink(self):
        for r in self:
            if r.state not in ('draft', 'cancel'):
                raise UserError('只可以刪除草稿狀態的單據')
        return super(BaseApprove, self).unlink()


class ApprovalActionWizard(models.TransientModel):
    """
        没有审核流的审核动作
    """
    _name = "to.approve.action.wizard"

    res_model = fields.Char()
    remark = fields.Text(string=u'備註')

    def submit(self):
        context = dict(self._context or {})

        active_ids = context.get('active_ids', [])
        model_ids = self.env[self.res_model].browse(active_ids)
        model_ids.action_submit()

    def reject(self):
        if not self.remark:
            raise UserError(u'簽核意見必填')
        context = dict(self._context or {})
        active_ids = context.get('active_ids', [])
        model_ids = self.env[self.res_model].browse(active_ids)
        remark = self.remark if self.remark else ''
        model_ids.action_reject(remark=remark)

    def approve(self):
        context = dict(self._context or {})
        active_ids = context.get('active_ids', [])
        model_ids = self.env[self.res_model].browse(active_ids)
        remark = self.remark if self.remark else ''
        model_ids.action_approve(remark=remark)

    def retract(self):
        context = dict(self._context or {})
        active_ids = context.get('active_ids', [])
        model_ids = self.env[self.res_model].browse(active_ids)
        remark = self.remark if self.remark else ''
        model_ids.action_cancel_approval(remark=remark)
